/**
 * @file
 * Custom event header file.
 *
 * Kisa provides spell checking as you type and displays the result in a small
 * window on your Desktop.
 *
 * Copyright (c) 2009 by Pete Black <theblackpeter@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation; either version 2 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 * Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * @author Pete Black <theblackpeter@gmail.com>
 */
#ifndef KISAEVENT_H
#define KISAEVENT_H

#include <QChar>
#include <QEvent>
#include <QtDebug>
#include "x11fix.h"

class QString;

/**
 * @class KisaEvent
 * The KisaEvent class provides a data type for storing X11 event information.
 * Any X11 event that is made available from the X servers event queue is
 * translated by the worker thread, KisaThread, to this internal structure.
 *
 * Event's that are of interest are keypress and window creation and visibility
 * notification events.
 *
 * Information about the originating X window is stored. If the event was a
 * keypress event then the character is stored. Visibility notification
 * events store the state of the window.
 *
 * @author Pete Black <theblackpeter@gmail.com>
 * @see Kisa
 * @see KisaLib
 * @see X11Lib
 */
class KisaEvent : public QEvent {

  public:
  /**
   * Default constructor. Creates a new KisaEvent object with default, @c NULL,
   * @c 0 or @c '\\0' values.
   *
   * @todo remove layout when KeyboardLayoutChange events start working again
   */
  KisaEvent() : QEvent(QEvent::None), m_key(QChar()), m_layout(QString()), m_state(-1), m_type(QEvent::None), m_window(77), m_xEvent(NULL) {
#ifdef FULL_DEBUG
    qDebug() << "kisaevent: kisaevent created" << "m_state" << m_state << "m_type" << m_type << "m_window" << m_window << "m_xEvent" << m_xEvent;
#endif
  };

  /**
   * Constructor. Creates a new generic KisaEvent object with type information
   * only.
   *
   * @param type the event type
   * @param window the event's X window id
   * @param xEvent pointer to the X event struct
   *
   * @todo remove layout when KeyboardLayoutChange events start working again
   */
  KisaEvent(const QEvent::Type& type, const Window& window, XEvent* xEvent = NULL) :
    QEvent(type), m_key(QChar()), m_layout(QString()), m_state(-1), m_type(type), m_window(window), m_xEvent(xEvent) {
#ifdef FULL_DEBUG
    qDebug() << "kisaevent: kisaevent created" << "created" << "m_state" << m_state << "m_type" << m_type << "m_window" << m_window << "m_xEvent" << m_xEvent;
#endif
  };

  /**
   * Constructor. Creates a new KisaEvent object that is intended to store
   * keypress information for the given X event.
   *
   * @param type the event type
   * @param window the event's X window id
   * @param key the character key that generated the event
   * @param xEvent pointer to the X event struct
   *
   * @todo remove layout when KeyboardLayoutChange events start working again
   */
  KisaEvent(const QEvent::Type& type, const QChar& key, const QString& layout, const Window& window, XEvent* xEvent = NULL) :
    QEvent(type), m_key(key), m_layout(layout), m_state(-1), m_type(type), m_window(window), m_xEvent(xEvent) {
#ifdef FULL_DEBUG
    qDebug() << "kisaevent: kisaevent created" << "m_state" << m_state << "m_type" << m_type << "m_window" << m_window << "m_xEvent" << m_xEvent << "m_key" << m_key;
#endif
  };

  /**
   * Constructor. Creates a new KisaEvent object that is intended to store
   * visibility state information for the given X event.
   *
   * @param type the event type
   * @param window the event's X window id
   * @param state the event's visibility state
   * @param xEvent pointer to the X event struct
   *
   * @todo remove layout when KeyboardLayoutChange events start working again
   */
  KisaEvent(const QEvent::Type& type, const int& state, const Window& window, XEvent* xEvent = NULL) :
    QEvent(type), m_key(QChar()), m_layout(QString()), m_state(state), m_type(QEvent::None), m_window(window), m_xEvent(xEvent) {
#ifdef FULL_DEBUG
    qDebug() << "kisaevent: kisaevent created" << "m_state" << m_state << "m_type" << m_type << "m_window" << m_window << "m_xEvent" << m_xEvent;
#endif
  };

  /**
   * Destructor.
   */
  virtual ~KisaEvent() {
#ifdef FULL_DEBUG
    qDebug() << "kisaevent: kisaevent destroyed";
#endif
  }

  /**
   * Checks wheat the event is of event type QEvent::None.
   *
   * @return @c true if the event is of type QEvent::None, @c false
   * otherwise
   */
  bool isNone();

  /**
   * Returns the character key for the QEvent::KeyPress event.
   *
   * @return the utf-8 character
   */
  const QChar key() const { return m_key; }

  /**
   * Gets the keyboard layout symbol from when this event was created. Only
   * used in the context of QEvent::KeyPress events.
   *
   * @return the keyboard layout symbol, for example "us" or an empty string
   *
   * @todo remove when KeyboardLayoutChange events start working again
   */
  const QString layout() { return m_layout; }

  /**
   * Gets the visibility state. The possible X visibility states are:
   *  @li @c VisibilityUnobscured
   *  @li @c VisibilityPartiallyObscured
   *  @li @c VisibilityFullyObscured
   *
   * @return the event's visibility state
   */
  int state() const { return m_state; }

  /**
   * Holds the event type. Currently used types are:
   *  @li QEvent::KeyPress for @c KeyPress X11 events
   *  @li QEvent::WindowActivate for @c VisibilityNotify, @c CreateNotify,
   *      and @c MapNotify X11 events
   */
  QEvent::Type type() const { return m_type; }

  /**
   * Returns the X11 window id for where the event originated from.
   *
   * @return the X window id
   */
  Window window() const { return m_window; }

  /**
   * Gets the original X11 event that caused the event.
   *
   * @return the X event struct
   */
  XEvent* xEvent() const { return m_xEvent; }

  private:

  /**
   * Holds the character key in a QEvent::KeyPress event.
   */
  QChar m_key;

  /**
   * Stores the current keyboard layout from where this event when this event
   * was received. Only used in QEvent::KeyPress events.
   *
   * @todo remove when KeyboardLayoutChange events start working again
   */

  QString m_layout;

  /**
   * Holds the visibility state in a visibility state change event.
   */
  int m_state;

  /**
   * Holds the event type.
   */
  QEvent::Type m_type;

  /**
   * Stores X11 window id from where the event originated.
   */
  Window m_window;

  /**
   * Pointer to the original X11 event.
   */
  XEvent* m_xEvent;
};

#endif
